<?php


/**
* Description of LiveRankings
*
* @author De Cramer Oliver
*/

namespace ManiaLivePlugins\MLEPP\Widgets\Widgets\Controlers\Defaults\LiveRankings;

use ManiaLivePlugins\MLEPP\Widgets\Widgets\Controlers\AutoHideDuringRace;
use ManiaLive\Data\Storage;
use ManiaLive\DedicatedApi\Connection;

use \ManiaLivePlugins\MLEPP\Widgets\Structures\smallPlayer;

class TimeAttack extends AutoHideDuringRace 
{
//   private $data = array();
   
   public function onInit()
   {
      parent::onInit();
      $this->setVersion(1);
      $this->enablePlayerClones();
      $this->setWhenToShow(1);
	  $this->setCanActivatePerf(true);
   }

   public function onUnload()
   {
      parent::onUnload();
   }

   public function onLoad()
   {
      parent::onLoad();
      $this->enableStorageEvents();
      $this->enableDedicatedEvents();
   }

   public function onReady() 
   {
      if ($this->storage->serverStatus->code == 4) 
      {
         foreach ($this->storage->players as $login => $player) 
         {
            parent::onPlayerConnect($login, false);
            $this->players[$login]->rank = -1;
         }
         foreach ($this->storage->spectators as $login => $player)
         {
            parent::onPlayerConnect($login, true);
            $this->players[$login]->rank = -1;
         }
         $this->data = array();
         
         $this->updateWidgetData($this->data);
         $this->forceUpdateWidget();
      }
      parent::onReady();
   }
   
    public function onPlayerDisconnect($login) 
   {
        //The parent handles the widget we need to call it
        parent::onPlayerDisconnect($login);
        gc_collect_cycles();
    }
   
   public function onPlayerConnect($login, $isSpec)
   {
        //The parent handles the widget we need to call it
        parent::onPlayerConnect($login, $isSpec);
      
      gc_collect_cycles();
      if (empty($this->data))
      {
         $this->players[$login]->rank = -1;
      } else
      {
         $max = count($this->data);
         for ($i = 1; $i<=$max; ++$i)
         {
            if ($this->data[$i]->login == $login)
            {
               $this->players[$login]->rank = $i;
               $this->players[$login]->score = $this->data[$i]->score;
               return;
            }
         }
         $this->players[$login]->rank = -1;
      }   
    }
   
   public function onPlayerNewBestTime($player, $best_old, $best_new) 
   {
      $login = $player->login;
      $oldRank = $this->players[$login]->rank;

      //Updating Ranking order in Data if needed
      if (empty($this->data))
      {
         //No data so player gets first liveRank...
         $this->players[$login]->rank = 1;
         $this->players[$login]->score = $best_new;
         $this->data[1] = $this->players[$login];
         $newRank=1;
      } else
      {
         $newRank = $this->getNewRank($oldRank,$best_new);
         $this->players[$login]->score = $best_new;
            if (($newRank <= $oldRank) || $oldRank == -1)
         {
            $this->players[$login]->rank = $newRank;
            $this->updateRanks($oldRank, $newRank, $this->players[$login]);
            }
      }
      //Updating The widgets if needed
      $this->updateWidget($oldRank, $newRank, $this->players[$login]);
   }
   
   private function getNewRank($oldRank,$score)
   {
      // limit rank checking between top 1 and $oldRank if previous score exist in data array
      // if not artificially set $oldRank as last (size of data array + 1)
      $max = ($oldRank == -1) ? (count($this->data) + 1) : $oldRank;

      for ($i = 1; $i < $max; ++$i)
      {
         if ($this->data[$i]->score > $score)
            return $i;
      }
      return $max;
   }

   private function updateRanks($old, $new, $player)
   {
      
      $max = count($this->data);
      
      // if $new > $max, then $new should be $max+1 - last ranking...
      if ($max < $new)
      {
         $this->data[$max+1] = $player;
         return;
        }
        // if same ranking, just update player data...
       if ($new == $old)
        {
            $this->data[$new]=$player;
            return;
        }    
      // if we get here, it means $new is not the last position and has changed...
      
      // if $oldRank set to -1, new entry added and data array size increased by 1, shifting down everybody from rank $new to end
      // if $oldRank set to something, entry already exists - overwriting $oldrank data with one above and then going up to $newRank -1
      //      and replacing $newRank with the new data
      $old = ($old == -1) ? ($max + 1) : $old;
         
      $i = $old;
      while($i > $new)
      {
         $this->data[$i] = $this->data[$i-1];
         if(isset($this->players[$this->data[$i]->login]))
            ++$this->players[$this->data[$i]->login]->rank;
         --$i;
      }
      $this->data[$new] = $player;
   }

   public function onStatusChanged($statusCode, $statusName)
   {
      parent::onStatusChanged($statusCode, $statusName);
      if ($statusCode != 4)
         return;
      foreach($this->players as &$player)
      {
         $player->rank = -1;
      }
      $this->data = array();

      $this->resetWidgetData();
      $this->forceUpdateWidget();
   }

    function destroy() 
   {
      parent::destroy();
      gc_collect_cycles();
   }

}

?>